<template>
    <div>
        <div class="bar">
            <div class="bar-label">
                <p>Group:</p>
            </div>
            <el-select-v2 
                ref="selectRef"
                class="select-bar"
                v-model="selectedGroup"
                filterable
                placeholder="Select Group"
                clearable
                highlight-current-row
                :options="options"
                @change="updatePage"
                >
            </el-select-v2>
            <div class="bar-label">
                <p>Highlight Nodes:</p>
            </div>
            <el-select-v2 
                ref="selectRef"
                class="select-bar"
                v-model="searchText"
                filterable
                placeholder="Select Highlight Nodes"
                clearable
                highlight-current-row
                :options="highlightOptions"
                @change="highlightNodes"
                >
            </el-select-v2>
            <el-button 
                class="select-button" 
                type="primary" 
                @click="resetView"
                >
                Reset View
            </el-button>
            <!-- <el-input
                v-model="searchText"
                placeholder="Input Gene Name"
                class="select-bar"
                @change="highlightNodes"
                style="width:200px; margin-bottom:10px"
            ></el-input> -->
            <div class="tips">
                <el-text type="info">
                    Tips: Please zoom in on the page and drag the center part of the label on the node to get a more accurate dragging experience.
                </el-text>
            </div>
        </div>
        <div>
            <div ref="cyContainer" style="width: 100%; height: 80vh;" ></div>
        </div>
    </div>
</template>

<script setup lang="ts" name="Cytoscape">
    import { ref, onBeforeMount, onMounted, computed } from 'vue';
    import Cytoscape from 'cytoscape';
    import { get, post } from '../../../axios/api';
    import coseBilkent from 'cytoscape-cose-bilkent';
    import { ElLoading, ElMessage } from 'element-plus'
    import fcose from "cytoscape-fcose";
    Cytoscape.use(fcose); 


    const cyContainer = ref(null);  // 引用容器
    let cy:any = null;  // Cytoscape 实例
    let elements:any = ref([])
    let selectedGroup:any = ref('group1')
    let loadingInstance:any = null
    const searchText = ref('');
    const colorMap:any = {
        'protein': '#807DBA',
        'drug': '#41AB5D',
        'gene': '#F79D95',
        'methy': '#FDAE61',
        'expression': 'BEDBEA',
    }

    const highlightOptions:any = ref([])

    const options = [
        {label: 'group1', value: 'group1'},
        {label: 'group2', value: 'group2'},
        {label: 'group3', value: 'group3'},
    ]

    function highlightNodes() {
        if (!cy) return;
        cy.nodes().removeClass('highlighted');
        
        // 获取搜索关键词，忽略前后空格，并转换为小写
        const searchVal = searchText.value;
        if (!searchVal) return;
        // 筛选出包含搜索关键词的节点（这里假设搜索节点的 label 属性）
        const nodesToHighlight = cy.nodes().filter((node: any) => {
            const label = node.data('label');
            return label && label == searchVal;
        });
        // 为符合条件的节点添加高亮样式类
        nodesToHighlight.addClass('highlighted');      
    }

    function generateNodeStyle(nodes: any[]) {
        return nodes.map((node: any) => ({
            selector: `node[id="${node.data.id}"]`,
            style: {
                'label': 'data(label)',
                'pie-size': '100%',
                'min-zoomed-font-size': 8,
                'width': 20,
                'height': 20,
                'border-width': 0,
                'background-image': 'none',
                'z-index': 2000,
                ...node.data.styles
            }
        }));
    }
    async function init() {
        loadingInstance = ElLoading.service({
            fullscreen: true,
            text: 'It takes a few seconds to load the graph...'
        })

        let res:any = await post('/get_group_cytoscape_data/', {group_name: selectedGroup.value})
        if (res && res.success) {
            elements.value = [...res.nodes, ...res.edges]
            const nodeStyles = generateNodeStyle(res.nodes);


            cy = Cytoscape({
                container: cyContainer.value,  // 绑定容器
                elements: elements.value,  // 设置图的数据
                style: [
                    ...nodeStyles,
                    {
                        selector: 'edge',
                        style: {
                            'width': 1,
                            'line-color': '#ccc',
                            'target-arrow-color': '#ccc',
                            'target-arrow-shape': 'triangle',
                            'curve-style': 'haystack', // [4]: 使用'haystack'表示直线，比'bezier'快得多
                            'opacity': 0.8, // [4]: 不透明的边比半透明的边快
                            'line-style': 'solid', // [4]: 避免虚线/点划线边
                            'arrow-scale': 0.8, // [4]: 如果语义上不需要，限制边的箭头
                            'z-index': 1,
                        }
                    },
                    {
                        selector: 'node.highlighted',
                        style: {
                            'border-color': '#CCFF00',
                            'border-width': 4,
                            'overlay-color': '#CCFF00',
                            'overlay-opacity': 0.5,
                            'overlay-padding': '3px',
                        }
                    },
                ],
                layout: {
                    name: "fcose",
                    quality: "proof", // 布局质量：'draft', 'default', 'proof'
                    numIter: 10000,
                    nodeRepulsion: 30000,
                    idealEdgeLength: 150,
                    randomize: true, // 是否随机初始位置
                    animate: true, // 关闭动画以加快布局
                    fit: true, // 布局完成后自动适应视口
                    padding: 30, // 视口边距
                    nodeDimensionsIncludeLabels: true, // [16]: 确保布局考虑标签尺寸
                    packComponents: true, // 启用组件打包（需要 cytoscape-layout-utilities）
                    edgeElasticity: 0.1
                },
                userPanningEnabled: true,  // 启用平移
                userZoomingEnabled: true   // 启用缩放
            });

            cy.on('tap', 'node', (evt:any) => {
                const node = evt.target;
                console.log(`Node clicked: ${node.id()}`);
            });

            cy.on('mouseover', 'node', (evt: any) => {
                const node = evt.target;
                node.style('label', node.data('label'));
            });

            cy.on('mouseout', 'node', (evt: any) => {
                const node = evt.target;
                node.style('label', '');
            });
            // cy.fit();
        }
        loadingInstance.close()
    }


    const updatePage = async () => {
        searchText.value = ''
        getOptions()
        init()
    };

    async function getOptions() {
        let res:any = {}
        try {
            res = await post('/get_cyto_gene/', {
                group_name: selectedGroup.value
            })
        } catch (error:any) {
            ElMessage({
                message: error,
                type: 'error',
            })
        }
        if (res && res.success) {
            highlightOptions.value = res.data
        } else {
            ElMessage({
                message: res.msg ? res.msg : "An error occured",
                type: 'error',
            })
            return
        }
    }

    function resetView() {
        if (!cy) return;
        cy.animate({
            fit: {
            eles: cy.elements(),
            padding: 30
            },
            zoom: 1,
            pan: { x: 0, y: 0 }
        }, {
            duration: 500
        });
    }


    // const filterMethod = (query:any) => {
    //     if (query) {
    //         const escapeStringRegexp = (string = '') => string.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/-/g, '\\x2d')
    //         const regexp = new RegExp(escapeStringRegexp(query), 'i')

    //         let filteredOptions = highlightOptions.value.filter((opt: any) => {
    //             return query ? regexp.test(opt.label || '') : true
    //         }).sort((a: any, b: any) => {
    //             const aStartsWith = a.label.toLowerCase().startsWith(query.toLowerCase());
    //             const bStartsWith = b.label.toLowerCase().startsWith(query.toLowerCase());
    //             return (aStartsWith === bStartsWith) ? (a.label.length < b.label.length ? -1 : 1) : (aStartsWith ? -1 : 1);
    //         })
    //         highlightOptions.value = filteredOptions.value
    //     } else {
    //         highlightOptions.value = highlightOptions.value
    //     }
    // };

    // 初始化 Cytoscape 实例
    onMounted(() => {
        getOptions()
        init();
    });
</script>

<style scoped>
    .bar {
        float: left;
        width: 100%;
        z-index: 99;
        display: flex;
        align-items: center;
    }
    
    .select-bar {
        z-index: 999;
        width: 200px;
        margin-right: 10px;
    }

    :deep(.el-input) {
        width: 500px !important;
        margin-bottom: 0 !important;
    }

    .bar-label {
        margin-right: 10px; /* 保持间距 */
        white-space: nowrap; /* 禁止换行 */
    }

    .select-button {
        margin-right: 20px;
    }

    .tips {
        width: fit-content;
    }
</style>